#include <Windows.h>
#include <tchar.h>
#include "resource.h"

struct SThreadInfo {
	HWND	hEdit;
	UINT	nMax;
	HANDLE	hEvent;
};

void AddText(HWND hEdit, TCHAR* szFormat, ...)
{
	va_list vaList;
	va_start(vaList, szFormat);
	TCHAR szInfo[1000 * 20];
	GetWindowText(hEdit, szInfo, _countof(szInfo));
	_vstprintf(_tcschr(szInfo, 0), szFormat, vaList);
	SetWindowText(hEdit, szInfo);
	va_end(vaList);
	SendMessage(hEdit, WM_VSCROLL, SB_BOTTOM, 0);

	return;
}

DWORD CALLBACK ThreadProc(LPVOID lpData)
{
	SThreadInfo* pti = (SThreadInfo*)lpData;
	for (int ii = 0; ii < pti->nMax; ii++)
	{
		AddText(pti->hEdit, _T("print value: %d\r\n"), (ii + 1));
	}
	SetEvent(pti->hEvent);

	return 0;
}

int CALLBACK DlgProc(HWND hDlg, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	switch (nMsg)
	{
		case WM_INITDIALOG:
		{
			SetWindowText(hDlg, _T("Demo0095"));

			UINT nWidth		= GetSystemMetrics(SM_CXSCREEN);
			UINT nHeight	= GetSystemMetrics(SM_CYSCREEN);
			RECT rtClient;
			GetClientRect(hDlg, &rtClient);
			SetWindowPos(hDlg, NULL, (nWidth - (rtClient.right - rtClient.left)) / 2, (nHeight - (rtClient.bottom - rtClient.top)) / 2, 0, 0, SWP_NOSIZE);
			SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

			break;
		}
		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				case IDC_BTNSTART:
				{				
					SetDlgItemText(hDlg, IDC_EDTINFO, _T(""));
					EnableWindow(GetDlgItem(hDlg, IDC_BTNSTART), FALSE);

					//CreateThread(NULL, 0, CreateProc, (LPVOID)hDlg, 0, NULL);
					
					SThreadInfo ti[] = {
						{GetDlgItem(hDlg, IDC_EDTTHREAD1), 100}, 
						{GetDlgItem(hDlg, IDC_EDTTHREAD2), 700},
						{GetDlgItem(hDlg, IDC_EDTTHREAD3), 400}, 
						{GetDlgItem(hDlg, IDC_EDTTHREAD4), 550}	
					};

					const UINT nCount = sizeof(ti) / sizeof(*ti);
					HANDLE hThreads[nCount]	= {0};
					HANDLE hEvents[nCount]	= {0};

					for (UINT ii = 0; ii < nCount; ii++)
					{
						hThreads[ii] = CreateThread(NULL, 0, ThreadProc, (LPVOID)&ti[ii], 0, NULL);
					}
					INT nTolCount = nCount;
					do { 
						DWORD dwIndex = MsgWaitForMultipleObjects(nTolCount, hThreads, FALSE, INFINITE, QS_ALLINPUT) - WAIT_OBJECT_0;
						if (dwIndex == nTolCount + WAIT_OBJECT_0)
						{
							MSG msg;
							while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
							{
								DispatchMessage(&msg);
								TranslateMessage(&msg);
							}
						} else if (dwIndex >=0 && dwIndex < nTolCount) {	
							AddText(GetDlgItem(hDlg, IDC_EDTINFO), _T("Thread(0x%X) has been returned\r\n"), hThreads[dwIndex]);
							CloseHandle(hThreads[dwIndex]);

							for (int ii = dwIndex; ii < nTolCount; ii++)
							{
								hThreads[ii] = hThreads[ii + 1];
							}
							nTolCount--;
						}
					} while (0 < nTolCount);

					for (int ii = 0; ii < nCount; ii++)
					{
						CloseHandle(hEvents[ii]);
					}
					
					EnableWindow(GetDlgItem(hDlg, IDC_BTNSTART), TRUE);
					break;
				}
			}
			break;
		}
		case WM_CLOSE:
		{
			PostQuitMessage(0);
			break;
		}
	}

	return 0;
}

BOOL WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR szCmdLine, int nShowCmd)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);

	return TRUE;
}